package com.daffodil.workable.factory.strategy;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatus.Series;

import com.daffodil.util.JacksonUtils;
import com.daffodil.util.StringUtils;
import com.daffodil.workable.entity.WorkableForm;
import com.daffodil.workable.entity.WorkableNode;
import com.daffodil.workable.entity.WorkableResult;
import com.daffodil.workable.factory.strategy.model.WorkableHttp;
import com.daffodil.workable.util.WorkableUtils;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;

/**
 * -任务工作流-http请求节点
 * @author yweijian
 * @date 2022年4月8日
 * @version 1.0
 * @description
 */
public class HttpWorkableStrategy extends DefaultWorkableStrategy {

    @SuppressWarnings("unchecked")
    @Override
    protected WorkableResult chain(WorkableNode workableNode, WorkableResult curtResult, WorkableResult lastResult) {

        WorkableForm workableForm = workableNode.getWorkableForm();
        if(StringUtils.isNull(workableForm)) {
            return curtResult.error("任务工作流执行失败，【{}】节点表单参数为空", workableNode.getName());
        }

        WorkableHttp workableHttp = JacksonUtils.toJavaObject(workableForm.getNodeForm(), WorkableHttp.class);
        if(StringUtils.isNull(workableHttp)) {
            return curtResult.error("任务工作流执行失败，【{}】节点表单参数为空或不规范", workableNode.getName());
        }
        if(StringUtils.isEmpty(workableHttp.getMethod())) {
            return curtResult.error("任务工作流执行失败，【{}】节点表单参数【{}】为空", workableNode.getName(), "method");
        }
        if(StringUtils.isEmpty(workableHttp.getUrl())) {
            return curtResult.error("任务工作流执行失败，【{}】节点表单参数【{}】为空", workableNode.getName(), "url");
        }

        Map<String, Object> variables = lastResult.getVariables();
        HttpMethod method = HttpMethod.valueOf(workableHttp.getMethod().toUpperCase());
        String url = this.charUnicodeEncoder(WorkableUtils.getExpressionValue(workableHttp.getUrl(), variables));
        String params = this.charUnicodeEncoder(WorkableUtils.getExpressionValue(workableHttp.getParams(), variables));
        String body = WorkableUtils.getExpressionValue(workableHttp.getBody(), variables);
        String header = WorkableUtils.getExpressionValue(workableHttp.getHeaders(), variables);
        Map<String, String> headers = JacksonUtils.toJavaObject(header, Map.class, () -> new HashMap<String, String>());
        url = url + (StringUtils.isNotEmpty(params) ? "?" + params : "");
        HttpRequest httpRequest = HttpRequest.of(url).method(Method.valueOf(method.name()));
        if(StringUtils.isNotEmpty(body)) {
            httpRequest.body(body);
        }
        if(StringUtils.isNotEmpty(headers)) {
            httpRequest.addHeaders(headers);
        }
        HttpResponse response = httpRequest.execute();
        
        Series series = HttpStatus.valueOf(response.getStatus()).series();
        curtResult.setStatus(series.equals(Series.SUCCESSFUL));
        curtResult.setMessage(response.body());
        curtResult.setVariables(JacksonUtils.toJavaObject(response.body(), Map.class, () -> new HashMap<String, String>()));
        
        return curtResult;
    }
    
    /**
     * -中文字符Unicode
     * @param content
     * @return
     */
    private String charUnicodeEncoder(String content) {
        if(StringUtils.isEmpty(content)) {
            return content;
        }
        Matcher matcher = Pattern.compile("[\u2e80-\ua4cf]").matcher(content);
        while (matcher.find()) {
            String text = matcher.group();
            content = content.replaceAll(text, URLEncoder.encode(text, StandardCharsets.UTF_8));
        }
        return content;
    }

}
